(function() {

    var ThresholdType = {

        LOG   : 0,

        INFO  : 1,

        WARN  : 2,

        ERROR : 3,

        DEBUG : 4

    };

    window.logger = {

        DEFAULT_NATIVE_FUNCTION_NAME : 'log',

        ALLOWED_FUNCTIONS : [
            { name : 'log',   threshold : ThresholdType.LOG   },
            { name : 'info',  threshold : ThresholdType.INFO  },
            { name : 'warn',  threshold : ThresholdType.WARN  },
            { name : 'error', threshold : ThresholdType.ERROR },
            { name : 'debug', threshold : ThresholdType.DEBUG }
        ],
    
        hasConsole : true,

        isWebKit : false,

        throwExceptionOnError : true,

        threshold : ThresholdType.ERROR,

        setThreshold : function(threshold) {
            this.threshold = threshold;
            this.initializeAllowedFunction();
        },

        throwError : function(funcName) {
            if (this.throwExceptionOnError && (funcName == 'error')) {
                throw 'See previous log message for error text.';
            }
        },

        initializeFunction : function(func) {
            if (!this.hasConsole || func.threshold > this.threshold) {
                this[func.name] = function() { };
                return;
            }

            var
            nativeFuncName = (!console[func.name] ? this.DEFAULT_NATIVE_FUNCTION_NAME : func.name),
            newFunc;

            if (!this.isWebKit) {
                newFunc = function() {
                    console[nativeFuncName].apply(window.console, arguments);
                    this.throwError(func.name);
                };
            } else {
                // Wraps arguments in array for a more visually pleasing visual output in WebKit browsers.
                newFunc = function() {
                    (console[nativeFuncName])(Array.prototype.slice.call(arguments));
                    this.throwError(func.name);
                };
            }

            this[func.name] = newFunc;
        },

        initializeAllowedFunction : function() {
            for (var i = 0; i < this.ALLOWED_FUNCTIONS.length; ++i) {
                this.initializeFunction(this.ALLOWED_FUNCTIONS[i]);
            }
        },

        initialize : function() {
            if (!window.console) {
                this.hasConsole = false;
            } else {
                try { console.log.apply(window, []); }
                catch (e) { this.isWebKit = true; }
            }

            this.initializeAllowedFunction();
        }

    };

    logger.ThresholdType = ThresholdType;
    logger.initialize();

})();
